package tcln.sors.client.core.mvc;

import java.util.Map;

import tcln.commons.assertion.Assert;
import tcln.sors.client.core.mvc.modelmapping.ModelDataMapper;
import tcln.sors.client.core.mvc.modelmapping.ModelDataPopulator;

/**
 * Base implementation for a {@link Controller} which stores the attached view and model data as well as convert DOM
 * entities to/from model data.
 * 
 * @param <M>
 *            Model class.
 * @author Truong Chau Lien Ngoc (lienngoc@gmail.com)
 */
public abstract class BaseController<M extends ModelData<?>> implements Controller<M> {
    
    /**
     * The attached view.
     */
    private View<?> view;
    
    /**
     * Current model data.
     */
    private M modelData;

    /**
     * Mapper for [object -> model data] conversion.
     */
    private ModelDataMapper dataMapper;
    
    /**
     * Populator for [model data -> object] conversion.
     */
    private ModelDataPopulator dataPopulator;

    /**
     * {@inheritDoc}
     */
    @Override
    public void setModelDataMapper(ModelDataMapper mapper) {
        this.dataMapper = mapper;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setModelDataPopulator(ModelDataPopulator populator) {
        this.dataPopulator = populator;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public M getCurrentModel() {
        return modelData;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setView(View<?> view) {
        Assert.ARGUMENTS.notNull(view, "View is missing");
        this.view = view;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void showView(boolean center) {
        this.view.show(center);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void showViewModal(boolean center) {
        this.view.showModal(center);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void initialize(Map<String, Object> requestParameters) {
        // no special initialization work is necessary
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onReady() {
        // by default, nothing is needed
    }

    /**
     * Returns current value of {@link #view}.
     * 
     * @return the {@link #view}.
     */
    protected View<?> getView() {
        return view;
    }

    /**
     * Returns current value of {@link #modelData}.
     * 
     * @return the {@link #modelData}.
     */
    protected M getModelData() {
        return modelData;
    }

    /**
     * Returns current value of {@link #dataMapper}.
     * 
     * @return the {@link #dataMapper}.
     */
    protected ModelDataMapper getDataMapper() {
        return dataMapper;
    }

    /**
     * Returns current value of {@link #dataPopulator}.
     * 
     * @return the {@link #dataPopulator}.
     */
    protected ModelDataPopulator getDataPopulator() {
        return dataPopulator;
    }

    /**
     * Sets new value for {@link #modelData}.
     * 
     * @param modelData
     *            the new modelData to set
     */
    protected void setModelData(M modelData) {
        this.modelData = modelData;
    }
}
